home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
xlib03.zip
/
XRECT.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-04-05
|
18KB
|
408 lines
;-----------------------------------------------------------------------
; MODULE XRECT
;
; Rectangle functions all MODE X 256 Color resolutions
;
; Compile with Tasm.
; C callable.
;
;
; ****** XLIB - Mode X graphics library ****************
; ****** ****************
; ****** Written By Themie Gouthas ****************
; ****** Aeronautical Research Laboratory ****************
; ****** Defence Science and Technology Organisation ****************
; ****** Australia ****************
;
; egg@dstos3.dsto.gov.au
; teg@bart.dsto.gov.au
;-----------------------------------------------------------------------
include xlib.inc
include xrect.inc
.code
; Plane masks for clipping left and right edges of rectangle.
LeftClipPlaneMask db 00fh,00eh,00ch,008h
RightClipPlaneMask db 00fh,001h,003h,007h
;---------------------------------------------------------------------------
; Mode X (320x240, 256 colors) rectangle solid colour fill routine.
;
; Based on code originally published in DDJ Mag by M. Abrash
;
; with TASM 2. C near-callable as:
;
; void x_rect_fill(int StartX, int StartY, int EndX, int EndY,
; unsigned int PageBase, unsigne int color);
;
;
_x_rect_fill proc
ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
push si ;preserve caller's register variables
push di
cld
mov ax,[_ScrnLogicalByteWidth]
mul [StartY] ;offset in page of top rectangle scan line
mov di,[StartX]
shr di,1 ;X/4 = offset of first rectangle pixel in scan
shr di,1 ; line
add di,ax ;offset of first rectangle pixel in page
add di,[PageBase] ;offset of first rectangle pixel in
; display memory
mov ax,SCREEN_SEG ;point ES:DI to the first rectangle
mov es,ax ; pixel's address
mov dx,SC_INDEX ;set the Sequence Controller Index to
mov al,MAP_MASK ; point to the Map Mask register
out dx,al
inc dx ;point DX to the SC Data register
mov si,[StartX]
and si,0003h ;look up left edge plane mask
mov bh,cs:LeftClipPlaneMask[si] ; to clip & put in BH
mov si,[EndX]
and si,0003h ;look up right edge plane
mov bl,cs:RightClipPlaneMask[si] ; mask to clip & put in BL
mov cx,[EndX] ;calculate # of addresses across rect
mov si,[StartX]
cmp cx,si
jle @@FillDone ;skip if 0 or negative width
dec cx
and si,not 011b
sub cx,si
shr cx,1
shr cx,1 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one byte to draw
and bh,bl ;there's only one byte, so combine the left
; and right edge clip masks
@@MasksSet:
mov si,[EndY]
sub si,[StartY] ;BX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov ah,byte ptr [Color] ;color with which to fill
mov bp,[_ScrnLogicalByteWidth] ;stack frame isn't needed any more
sub bp,cx ;distance from end of one scan line to start
dec bp ; of next
@@FillRowsLoop:
push cx ;remember width in addresses - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the left edge
dec cx ;count off left edge byte
js @@FillLoopBottom ;that's the only byte
jz @@DoRightEdge ;there are only two bytes
mov al,00fh ;middle addresses drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
mov al,ah ;put color in AL
rep stosb ;draw middle addresses four pixels apiece
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
mov al,ah ;put color in AL
stosb ;draw the right edge
@@FillLoopBottom:
add di,bp ;point to start of the next scan line of
; the rectangle
pop cx ;retrieve width in addresses - 1
dec si ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
pop di ;restore caller's register variables
pop si
pop bp ;restore caller's stack frame
ret
_x_rect_fill endp
;---------------------------------------------------------------------------
; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.
; Upper left corner of pattern is always aligned to a multiple-of-4
; row and column. Works on all VGAs. Uses approach of copying the
; pattern to off-screen display memory, then loading the latches with
; the pattern for each scan line and filling each scan line four
; pixels at a time. Fills up to but not including the column at EndX
; and the row at EndY. No clipping is performed. All ASM code tested
;
;
; Based on code originally published in DDJ Mag by M. Abrash
;
;
; C near-callable as:
;
; void x_rect_pattern(int StartX, int StartY, int EndX, int EndY,
; unsigned int PageBase, char far * Pattern);
_x_rect_pattern proc
ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword
LOCAL NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
sub sp,LocalStk ;allocate space for local vars
push si ;preserve caller's register variables
push di
push ds
cld
mov ax,SCREEN_SEG ;point ES to display memory
mov es,ax
;copy pattern to display memory buffer
lds si,dword ptr [Pattern] ;point to pattern to fill with
mov di,PATTERN_BUFFER ;point ES:DI to pattern buffer
mov dx,SC_INDEX ;point Sequence Controller Index to
mov al,MAP_MASK ; Map Mask
out dx,al
inc dx ;point to SC Data register
mov cx,4 ;4 pixel quadruplets in pattern
@@DownloadPatternLoop:
mov al,1 ;
out dx,al ;select plane 0 for writes
movsb ;copy over next plane 0 pattern pixel
dec di ;stay at same address for next plane
mov al,2 ;
out dx,al ;select plane 1 for writes
movsb ;copy over next plane 1 pattern pixel
dec di ;stay at same address for next plane
mov al,4 ;
out dx,al ;select plane 2 for writes
movsb ;copy over next plane 2 pattern pixel
dec di ;stay at same address for next plane
mov al,8 ;
out dx,al ;select plane 3 for writes
movsb ;copy over next plane 3 pattern pixel
; and advance address
loop @@DownloadPatternLoop
pop ds
mov dx,GC_INDEX ;set the bit mask to select all bits
mov ax,00000h+BIT_MASK ; from the latches and none from
out dx,ax ; the CPU, so that we can write the
; latch contents directly to memory
mov ax,[StartY] ;top rectangle scan line
mov si,ax
and si,011b ;top rect scan line modulo 4
add si,PATTERN_BUFFER ;point to pattern scan line that
; maps to top line of rect to draw
mov dx,[_ScrnLogicalByteWidth]
mul dx ;offset in page of top rect scan line
mov di,[StartX]
mov bx,di
shr di,1 ;X/4 = offset of first rectangle pixel in scan
shr di,1 ; line
add di,ax ;offset of first rectangle pixel in page
add di,[PageBase] ;offset of first rectangle pixel in
; display memory
and bx,0003h ;look up left edge plane mask
mov ah,cs:LeftClipPlaneMask[bx] ; to clip
mov bx,[EndX]
and bx,0003h ;look up right edge plane
mov al,cs:RightClipPlaneMask[bx] ; mask to clip
mov bx,ax ;put the masks in BX
mov cx,[EndX] ;calculate # of addresses across rect
mov ax,[StartX]
cmp cx,ax
jle @@FillDone ;skip if 0 or negative width
dec cx
and ax,not 011b
sub cx,ax
shr cx,1
shr cx,1 ;# of addresses across rectangle to fill - 1
jnz @@MasksSet ;there's more than one pixel to draw
and bh,bl ;there's only one pixel, so combine the left
; and right edge clip masks
@@MasksSet:
mov ax,[EndY]
sub ax,[StartY] ;AX = height of rectangle
jle @@FillDone ;skip if 0 or negative height
mov [Height],ax
mov ax,[_ScrnLogicalByteWidth]
sub ax,cx ;distance from end of one scan line to start
dec ax ; of next
mov [NextScanOffset],ax
mov [RectAddrWidth],cx ;remember width in addresses - 1
mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
; (SC Index still points to Map Mask)
@@FillRowsLoop:
mov cx,[RectAddrWidth] ;width across - 1
mov al,es:[si] ;read display memory to latch this scan
; line's pattern
inc si ;point to the next pattern scan line, wrapping
jnz short @@NoWrap ; back to the start of the pattern if
sub si,4 ; we've run off the end
@@NoWrap:
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
stosb ;draw the left edge (pixels come from latches;
; value written by CPU doesn't matter)
dec cx ;count off left edge address
js @@FillLoopBottom ;that's the only address
jz @@DoRightEdge ;there are only two addresses
mov al,00fh ;middle addresses drawn 4 pixels at a pop
out dx,al ;set middle pixel mask to no clip
rep stosb ;draw middle addresses four pixels apiece
; (from latches; value written doesn't matter)
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
stosb ;draw the right edge (from latches; value
; written doesn't matter)
@@FillLoopBottom:
add di,[NextScanOffset] ;point to the start of the next scan
; line of the rectangle
dec word ptr [Height] ;count down scan lines
jnz @@FillRowsLoop
@@FillDone:
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop di ;restore caller's register variables
pop si
mov sp,bp ;discard storage for local variables
pop bp ;restore caller's stack frame
ret
_x_rect_pattern endp
;-----------------------------------------------------------------------
; Mode X (320x240, 256 colors) display memory to display memory copy
; routine. Left edge of source rectangle modulo 4 must equal left edge
; of destination rectangle modulo 4. Works on all VGAs. Uses approach
; of reading 4 pixels at a time from the source into the latches, then
; writing the latches to the destination. Copies up to but not
; including the column at SrcEndX and the row at SrcEndY. No
; clipping is performed. Results are not guaranteed if the source and
; destination overlap.
;
;
; Based on code originally published in DDJ Mag by M. Abrash
;
;C near-callable as:
; void x_cp_vid_rect(int SrcStartX, int SrcStartY,
; int SrcEndX, int SrcEndY, int DestStartX,
; int DestStartY, unsigned int SrcPageBase,
; unsigned int DestPageBase, int SrcBitmapWidth,
; int DestBitmapWidth);
_x_cp_vid_rect proc
ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word,SrcBitmapW:word,DestBitmapW:word
LOCAL SrcNextOffs:word,DestNextOffs:word,RectAddrW:word,Height:word=LocalStk
push bp ;preserve caller's stack frame
mov bp,sp ;point to local stack frame
sub sp,LocalStk ;allocate space for local vars
push si ;preserve caller's register variables
push di
push ds
cld
mov dx,GC_INDEX ;set the bit mask to select all bits
mov ax,00000h+BIT_MASK ; from the latches and none from
out dx,ax ; the CPU, so that we can write the
; latch contents directly to memory
mov ax,SCREEN_SEG ;point ES to display memory
mov es,ax
mov ax,[DestBitmapW]
shr ax,2 ;convert to width in addresses
mul [DestStartY] ;top dest rect scan line
mov di,[DestStartX]
shr di,2 ;X/4 = offset of first dest rect pixel in
; scan line
add di,ax ;offset of first dest rect pixel in page
add di,[DestPageBase] ;offset of first dest rect pixel
; in display memory
mov ax,[SrcBitmapW]
shr ax,2 ;convert to width in addresses
mul [SrcStartY] ;top source rect scan line
mov si,[SrcStartX]
mov bx,si
shr si,2 ;X/4 = offset of first source rect pixel in
; scan line
add si,ax ;offset of first source rect pixel in page
add si,[SrcPageBase] ;offset of first source rect
; pixel in display memory
and bx,0003h ;look up left edge plane mask
mov ah,cs:LeftClipPlaneMask[bx] ; to clip
mov bx,[SrcEndX]
and bx,0003h ;look up right edge plane
mov al,cs:RightClipPlaneMask[bx] ; mask to clip
mov bx,ax ;put the masks in BX
mov cx,[SrcEndX] ;calculate # of addresses across
mov ax,[SrcStartX] ; rect
cmp cx,ax
jle @@CopyDone ;skip if 0 or negative width
dec cx
and ax,not 011b
sub cx,ax
shr cx,2 ;# of addresses across rectangle to copy - 1
jnz @@MasksSet ;there's more than one address to draw
and bh,bl ;there's only one address, so combine the left
; and right edge clip masks
@@MasksSet:
mov ax,[SrcEndY]
sub ax,[SrcStartY] ;AX = height of rectangle
jle @@CopyDone ;skip if 0 or negative height
mov [Height],ax
mov ax,[DestBitmapW]
shr ax,2 ;convert to width in addresses
sub ax,cx ;distance from end of one dest scan line
dec ax ; to start of next
mov [DestNextOffs],ax
mov ax,[SrcBitmapW]
shr ax,2 ;convert to width in addresses
sub ax,cx ;distance from end of one source scan line
dec ax ; to start of next
mov [SrcNextOffs],ax
mov [RectAddrW],cx ;remember width in addresses - 1
mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
; (SC Index still points to Map Mask)
mov ax,es ;DS=ES=screen segment for MOVS
mov ds,ax
@@CopyRowsLoop:
mov cx,[RectAddrW] ;width across - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
movsb ;copy the left edge (pixels go through
; latches)
dec cx ;count off left edge address
js @@CopyLoopBottom ;that's the only address
jz @@DoRightEdge ;there are only two addresses
mov al,00fh ;middle addresses are drawn 4 pix per go
out dx,al ;set the middle pixel mask to no clip
rep movsb ;draw the middle addresses four pix per go
; (pixels copied through latches)
@@DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
movsb ;draw the right edge (pixels copied through
; latches)
@@CopyLoopBottom:
add si,[SrcNextOffs] ;point to the start of
add di,[DestNextOffs] ; next source & dest lines
dec word ptr [Height] ;count down scan lines
jnz @@CopyRowsLoop
@@CopyDone:
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop ds
pop di ;restore caller's register variables
pop si
mov sp,bp ;discard storage for local variables
pop bp ;restore caller's stack frame
ret
_x_cp_vid_rect endp
end